// RegexpHandler.h Added by Sulan 2005-05-20
// Pothead split to .cpp and changed stuff

#include "stdinc.h"
#include "DCPlusPlus.h"
#include "ResourceManager.h"
#include "DebugManager.h"
#include "..\pcre\pcrecpp.h"
#include "RegexpHandler.h"
using namespace pcrecpp;
	//Check if regexp is valid
	bool RegexpHandler::isValid(const string& aExp, const bool& caseSensitive ) {
		return processRegExp(true, caseSensitive ? aExp : "(?i)" + aExp, "");
	}

	// Check if string is an IP
	bool RegexpHandler::isIp(const string& aString) {
		return RegexpHandler::matchProfile(aString, "\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b") ? true : false;
	}
	//Gabberworld
	bool RegexpHandler::isMatch(const string& aString, const string& aExp) {
		string e = aString;
		//string s;
		//pcrecpp::RE("(\\r|\\n|\\t)+").GlobalReplace("", &e); //is there a better solution for that ? maybe he need a buffer?
		pcrecpp::RE re("^(..*)");
		if(/*re.FullMatch(e, &s) && */re.FullMatch(aExp)) {
			return RegexpHandler::matchProfile( e, aExp ) ? true : false;
			//return RegexpHandler::matchProfile( s, aExp ) ? true : false;
		}
		return false;
	}
	//end
	//Check if regexp is valid and return if it is a match or no match
	string RegexpHandler::matchExp(const string& aExp, const string& aString, const bool& caseSensitive) {
		if(!isValid(aExp, caseSensitive))
			return CSTRING(S_INVALID); 
		return matchProfile(aString, aExp, caseSensitive, true) ? CSTRING(S_MATCH) : CSTRING(S_MISSMATCH);
	}

	//Check if regexp is valid and return if it is a match or not
	bool RegexpHandler::matchProfile(const string& aString, const string& aExp, const bool& caseSensitive, const bool& alreadyCheckedValidity) {
		DETECTION_DEBUG("\t\tMatching String: " + aString + " to Profile: " + aExp);
		if(!alreadyCheckedValidity)
			if (!isValid(aExp, caseSensitive))
				return false;
		return processRegExp(false, caseSensitive ? aExp : "(?i)" + aExp, aString);
	}

	//Format the params so we can view the regexp string
	string RegexpHandler::formatRegExp(const string& msg, StringMap& params) {
		string result = msg;
		string::size_type i, j, k;
		i = 0;
		while (( j = result.find("%[", i)) != string::npos) {
			if((result.size() < j + 2) || ((k = result.find(']', j + 2)) == string::npos))
				break;
			string name = result.substr(j + 2, k - j - 2);
			StringMapIter smi = params.find(name);
			if(smi != params.end()) {
				result.replace(j, k-j + 1, smi->second);
				i = j + smi->second.size();
			} else {
				i = k + 1;
			}
		}
		return result;
	}

	//Return the tags version number for %[version]
	string RegexpHandler::getVersion(const string& aExp, const string& aTag) {
		string::size_type i = aExp.find("%[version]");
		if (i == string::npos) { 
			i = aExp.find("%[version2]"); 
			return splitVersion(aExp.substr(i + 11), splitVersion(aExp.substr(0, i), aTag, false), true);
		}
		return splitVersion(aExp.substr(i + 10), splitVersion(aExp.substr(0, i), aTag, false), true);
	}

	// Used by getVersion to extract bits of the tag, to eventually return the version number
	string RegexpHandler::splitVersion(const string& aExp, const string& aTag, const bool firstPart) {
		if(!isValid(aExp))
			return "";
		return processRegExp(aExp, aTag, firstPart);
	}

	bool RegexpHandler::processRegExp(const bool forValid, const string& aExp, const string& aString) {
		pcrecpp::RE reg(aExp);
		return forValid ? (reg.NumberOfCapturingGroups() != -1 ? true : false) : reg.PartialMatch(aString);
	}

	string RegexpHandler::processRegExp(const string& aExp, const string& aString, const bool firstPart) {
		string part1, part2;
		pcrecpp::RE reg(firstPart ? "(.*)(" + aExp + ")" : "(" + aExp + ")(.*)");
		reg.PartialMatch(aString, &part1, &part2);
		return firstPart ? part1 : part2;
	}
/**
 * @file
 * $Id: RegexpHandler.cpp 273 2005-07-19 18:20:48Z Pothead $
 */